5.1. 구조체 정의 및 인스턴스화

구조체

구조체는 튜플과 비슷하다.
구성 요소의 타입은 자유롭다.
또 각각의 요소에 이름을 붙일 수 있다.
이를 통해 명확한 의미를 부여하고 요소 접근에 순서에 의존하지 않아도 된다.

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

만들고 나면 인스턴스를 만들어야 비로소 사용할 수 있다.
필드의 순서는 자유롭게 설정할 수 있다.

fn main() {
    let mut user1 = User {
        active: true,
        username: String::from("someusername123"),
        email: String::from("someone@example.com"),
        sign_in_count: 1,
    };

    user1.email = String::from("anotheremail@example.com");
}

mut을 통해 값을 바꿔줬다.
가변성은 전체 인스턴스에 부여된다.
.을 통해 필드에 접근한다.

필드 초기화 축약법

Pasted image 20240501130357.png
인스턴스를 빠르게 초기화하는 함수를 만들어주었다.
표시가 되었듯, 필드 초기화를 할 때, 변수명과 필드명이 같다면 축약이 가능하다.

fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username,
        email,
        sign_in_count: 1,
    }
}

구조체 업데이트 문법

기존의 인스턴스에 있는 값을 활용하여 새로운 인스턴스를 만들고 싶을 수도 있다.

fn main() {
    // --생략--

    let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };
}

이런 식으로 ..을 사용하면 인스턴스를 보다 편하게 만들 수 있다.
참고로 이렇게 사용하면 user1의 힙데이터는 이동되어 사용할 수 없게 된다.
하지만 업데이트를 할 때 힙데이터에 해당하는 부분들을 전부 새로운 변수에서 새롭게 초기화했다면, user1을 그대로 사용할 수 있다.
다른 값들은 Copy 트레이트가 구현되었기에 스택에 저장된 데이터로서 복사가 일어나는 것이다.

튜플 구조체

러스트에서는 튜플과 비슷하게 생긴 구조체를 사용할 수 있다.
필드에 이름을 넣지 않고 타입만 적은 형태이다.
어떤 튜플 형태에 이름을 붙이고 싶거나, 구조체처럼 장황하게 하고 싶지 않을 때 유용하다.

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

fn main() {
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
}

Color와 Point는 다른 구조체이기에 값을 서로 전달하는 것이 불가능하다.

유사 유닛 구조체

필드가 없는 구조체를 정의하는 것도 가능하다.
값 없는 튜플을 유닛이라 부르듯, 유닛 구조체(unit-like struct)라 부른다.
어떤 타입에 대해 트레이트를 구현하나 내부에 데이터가 필요하지 않을 때 유용하다.

struct AlwaysEqual;

fn main() {
    let subject = AlwaysEqual;
}

이런 식으로 일절 괄호를 넣지 않는다.
AlwaysEqual의 모든 인스턴스는 언제나 다른 모든 인스턴스와 같도록 하는 동작을 구현하고, 이미 알고 있는 결과값의 테스트 용도로 사용할 때 유용하다.
10. 제네릭 타입, 트레이트, 라이프타임장에서 더 자세히 보게 될 것이다.

구조체 데이터 소유권

위의 User 구조체에서 필드에 &str을 쓰는 것이 가능했을 것이다.
String을 쓴 것은 인스턴스가 유효한 동안은 모든 필드가 유효한 것을 보장하기 위해서이다.
10. 제네릭 타입, 트레이트, 라이프타임을 배우고 나면 소유권 없는 문자열 슬라이스를 사용하는 것도 가능하다.
라이프타임을 명시하고 활용하는 법을 나중에 익혀보자.